package com.tmt.fileservice.impl;


import com.tmt.fileservice.IFileDataResolver;
import com.tmt.fileservice.IFileDispatcher;
import com.tmt.fileservice.IFileService;
import com.tmt.fileservice.IFileStorage;
import com.tmt.fileservice.exception.FileLoadException;
import com.tmt.fileservice.exception.FileValidateException;

import java.io.File;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Date;

/**
 * Created by ThreeManTeam on 2017/5/24.
 */

public class DefaultFileService implements IFileService {

    private IFileStorage fileStorage;

    private IFileDispatcher fileDispatcher;

    private static DefaultFileService instance;

    private static Thread expiredFileProcessor = null;

    private DefaultFileService(IFileDispatcher dispatcher, IFileStorage fileStore){
        this.fileDispatcher = (dispatcher != null ? dispatcher : DefaultFileDispatcher.getInstance());
        this.fileStorage = (fileStore != null ? fileStore : DefaultFileStorage.getInstance(null));
    }

    public static synchronized DefaultFileService getInstance(){
        return instance;
    }

    public static synchronized DefaultFileService createInstance(IFileDispatcher dispatcher, IFileStorage fileStore){
        if (instance == null) {
            instance = new DefaultFileService(dispatcher, fileStore);
            expiredFileProcessor = bindFileExpiredProcessor(instance,  dispatcher.getTmpFileDir(), dispatcher.getFileExpiredTime());
        }
        return instance;
    }

    @Override
    public IFileDispatcher getFileDispatcher() {
        return fileDispatcher;
    }

    @Override
    public IFileStorage getFileStorage() {
        return fileStorage;
    }

    @Override
    public void save(String filePath, IFileDataResolver resolver) throws FileValidateException {
        String validatorName = fileDispatcher.getValidatorNameByPath(filePath);
        fileStorage.save(filePath, resolver, validatorName);
    }

    @Override
    public void load(String filePath, OutputStream out) throws FileLoadException {
        fileStorage.load(filePath, out);
    }

    @Override
    public void saveByUrl(String fileUrl, IFileDataResolver resolver) throws FileValidateException {
        String filePath = fileDispatcher.fileUrlToPath(fileUrl);
        String validatorName = fileDispatcher.getValidatorNameByUrl(fileUrl);
        fileStorage.save(filePath, resolver, validatorName);
    }

    @Override
    public void loadByUrl(String fileUrl, OutputStream out) throws FileLoadException {
        String filePath = fileDispatcher.fileUrlToPath(fileUrl);
        fileStorage.load(filePath, out);
    }

    @Override
    public void deleteFile(String filePath) {
        fileStorage.delete(filePath);
    }

    @Override
    public void deleteFileExclude(String filePath) {
        File file = new File(filePath);
        if (!file.getParentFile().exists())
            return;

        File[] allFile = file.getParentFile().listFiles();
        Arrays.stream(allFile).forEach(x->{
            if (filePath.endsWith("/" + x.getName()))
                return;
            fileStorage.delete(x.getPath());
        });
    }

    @Override
    public long getFileSize(String filePath) {
        return fileStorage.getFileSize(filePath);
    }


    private static Thread bindFileExpiredProcessor(IFileService iFileService, String filePath, long fileExpiredTime){
        if (fileExpiredTime <= 0)
            return null;

        Thread thread = new Thread(() -> {
            while(true) {
                synchronized (iFileService) {
                    try {
                        iFileService.wait(60 * 1000);
                    } catch (Exception ex) {
                    }
                }

                try {
                    //System.out.println("----------开始清理过期文件-------------");
                    //删除filePath目录（含子目录）下的所有过期文件。
                    deleteExpiredFile(iFileService, filePath, fileExpiredTime);
                    //System.out.println("----------过期文件清理结束-------------");
                }catch (Exception ex){}
            }
        });
        thread.setDaemon(true);
        thread.start();
        return thread;
    }

    private static void deleteExpiredFile(IFileService iFileService, String fileDir, long fileExpiredTime){
        File file = new File(fileDir);
        if (file.exists() && file.isFile()){
            Date dt = new Date(file.lastModified() + fileExpiredTime * 1000);
            if (dt.before(new Date())) {
                iFileService.deleteFile(fileDir);
            }
            return;
        }

        File[] allExpiredFiles = file.listFiles(x->{
            Date dt = new Date(file.lastModified() + fileExpiredTime * 1000);
            return x.isFile() && dt.before(new Date());
        });

        Arrays.stream(allExpiredFiles).forEach(x->iFileService.deleteFile(x.getPath()));

        //删除自录下的过期文件。
        File[] childDirArray = file.listFiles(x-> x.isDirectory());
        Arrays.stream(childDirArray).forEach(x->deleteExpiredFile(iFileService, x.getPath(), fileExpiredTime));
    }
}
